package escape;


import org.w3c.dom.events.Event;
import org.w3c.dom.events.EventListener;

/**
 * this逸出
 */
/**
 * 内部类或者匿名内部类构造的时候会隐式把外部类(即this)作为一个参数传递给内部类的构造方法
 **/
/**
 * ThisEscape当一个线程初始化执行到source.registerListener时，将EventListener发布出去了
 * 另一个线程获取到EventSource对EventListener进行操作，由于内部类会自动的持有其外部类（这里是ThisEscape）的this引用，
 * 但是由于此时外部类还没完全初始化完，就会产生异常
 **/
public class ThisEscape {
    public final int id;
    public final String name;

    static ThisEscape obj;

    public ThisEscape() {
        id = 1;
        name = "flysqrlboy";
        //将this逃逸抛出给线程B
        //obj = this;
    }

    public ThisEscape(EventSource<EventListener> source) {
        id = 1;
        //内部类是可以直接访问外部类的成员变量的（外部类引用this被内部类获取了）
        source.registerListener(new EventListener() {
            @Override
            public void handleEvent(Event evt) {
                System.out.println("id: " + ThisEscape.this.id);
                System.out.println("name: " + ThisEscape.this.name);
                doSomething(evt);
            }
        });
        name = "flysqrlboy";
    }

    public void doSomething(Event e) {
        System.out.println(e);
    }

    public static void main(String[] args) {
        //线程A：模拟构造器中this逃逸,将未构造完全对象引用抛出
        Thread threadA = new Thread(new Runnable() {
            @Override
            public void run() {
                obj = new ThisEscape();
            }
        });

        //线程B：读取对象引用，访问id/name变量
        Thread threadB = new Thread(new Runnable() {
            @Override
            public void run() {
                ThisEscape objB = obj;
                try {
                    System.out.println(objB.id);
                } catch (Exception e) {
                    System.out.println("发生空指针错误：id未被初始化");
                }
                try {
                    System.out.println(objB.name);
                } catch (Exception e) {
                    System.out.println("发生空指针错误：name未被初始化");
                }
            }
        });

        threadA.start();
        threadB.start();
    }

}
